package com.lineage.server;

import com.lineage.echo.ClientExecutor;
import com.lineage.echo.QuitGame;
import com.lineage.list.OnlineUser;
import com.lineage.server.datatables.lock.AccountReading;
import com.lineage.server.datatables.lock.CharMapTimeReading;
import com.lineage.server.datatables.lock.ServerReading;
import com.lineage.server.model.Instance.L1PcInstance;
import com.lineage.server.serverpackets.S_Disconnect;
import com.lineage.server.serverpackets.S_ServerMessage;
import com.lineage.server.serverpackets.ServerBasePacket;
import com.lineage.server.templates.L1Account;
import com.lineage.server.thread.GeneralThreadPool;
import com.lineage.server.world.World;
import java.util.Collection;
import java.util.Iterator;
import java.util.Random;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Shutdown extends Thread {
  public static final int SIGTERM = 0;
  
  public static final int GM_SHUTDOWN = 1;
  
  public static final int GM_RESTART = 2;
  
  public static final int ABORT = 3;
  
  protected static final Random _random = new Random();
  
  private static final Log _log = LogFactory.getLog(Shutdown.class);
  
  public static boolean SHUTDOWN;
  
  public static boolean isSHUTDOWN;
  
  private static Shutdown _instance;
  
  private static Shutdown _counterInstance = null;
  
  private static boolean _isMsg;
  
  private int _secondsShut;
  
  private int _shutdownMode;
  
  private int _overTime;
  
  static {
    SHUTDOWN = false;
    _isMsg = false;
    isSHUTDOWN = false;
  }
  
  public Shutdown() {
    this._overTime = 5;
    this._secondsShut = -1;
    this._shutdownMode = 0;
  }
  
  public Shutdown(int seconds, boolean restart) {
    this._overTime = 5;
    if (seconds < 0)
      seconds = 0; 
    this._secondsShut = seconds;
    if (restart) {
      this._shutdownMode = 2;
    } else {
      this._shutdownMode = 1;
    } 
  }
  
  public static Shutdown getInstance() {
    if (_instance == null)
      _instance = new Shutdown(); 
    return _instance;
  }
  
  public void run() {
    if (this == _instance) {
      if (this._shutdownMode != 3)
        try {
          saveData();
          _log.warn("正在关闭玩家连线中...");
          Thread.sleep(3000L);
          while (this._overTime > 0) {
            _log.warn("距离核心完全关闭 : " + this._overTime + "秒!");
            this._overTime--;
            Thread.sleep(1000L);
          } 
          int list = OnlineUser.get().size();
          _log.warn("核心关闭残余连线帐号数量: " + list);
          Thread.sleep(1000L);
          if (list >= 0) {
            Iterator<String> iterator = OnlineUser.get().map().keySet().iterator();
            while (iterator.hasNext()) {
              String account = iterator.next();
              _log.warn("核心关闭残留帐号: " + account);
            } 
          } 
        } catch (InterruptedException e) {
          _log.error(e.getLocalizedMessage(), e);
        }  
    } else {
      countdown();
      if (this._shutdownMode != 3)
        switch (this._shutdownMode) {
          case 1:
            _instance.setMode(1);
            System.exit(0);
            break;
          case 2:
            _instance.setMode(2);
            System.exit(1);
            break;
        }  
    } 
  }
  
  public void startShutdown(L1PcInstance activeChar, int seconds, boolean restart) {
    if (_counterInstance != null)
      return; 
    if (activeChar != null)
      _log.warn(String.valueOf(String.valueOf(activeChar.getName())) + " 启动关机计时: " + seconds + " 秒!"); 
    if (_counterInstance != null)
      _counterInstance._abort(); 
    _counterInstance = new Shutdown(seconds, restart);
    GeneralThreadPool.get().execute(_counterInstance);
  }
  
  public void abort(L1PcInstance activeChar) {
    if (_counterInstance != null)
      _counterInstance._abort(); 
  }
  
  private void setMode(int mode) {
    this._shutdownMode = mode;
  }
  
  private void _abort() {
    this._shutdownMode = 3;
  }
  
  private void countdown() {
    try {
      SHUTDOWN = true;
      World.get().broadcastPacketToAll((ServerBasePacket)new S_ServerMessage(72, String.valueOf(this._secondsShut)));
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
      return;
    } finally {
      if (this._shutdownMode != 3) {
        saveData();
      } else {
        this._secondsShut = -1;
        this._shutdownMode = 0;
        _counterInstance = null;
      } 
    } 
    if (this._shutdownMode != 3) {
      saveData();
    } else {
      this._secondsShut = -1;
      this._shutdownMode = 0;
      _counterInstance = null;
    } 
  }
  
  private synchronized void saveData() {
    try {
      World.get().broadcastPacketToAll((ServerBasePacket)new S_Disconnect());
      Collection<ClientExecutor> list = OnlineUser.get().all();
      if (!_isMsg) {
        _isMsg = true;
        _log.info("人物/物品 资料的存档 - 关闭核心前连线帐号数量: " + list.size());
      } 
      Iterator<ClientExecutor> iterator = list.iterator();
      while (iterator.hasNext()) {
        ClientExecutor client = iterator.next();
        L1PcInstance tgpc = client.getActiveChar();
        if (tgpc != null) {
          QuitGame.quitGame(tgpc);
          client.setActiveChar(null);
          client.kick();
          client.close();
        } 
        L1Account value = client.getAccount();
        if (value != null) {
          if (value.is_isLoad())
            OnlineUser.get().remove(client.getAccountName()); 
          value.set_isLoad(false);
          AccountReading.get().updateLan(client.getAccountName(), false);
        } 
      } 
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      AccountReading.get().updateLan();
      CharMapTimeReading.get().saveAllTime();
      ServerReading.get().isStop();
    } 
  }
  
  private void onlineusersave() {
    Collection<ClientExecutor> list = OnlineUser.get().all();
    Iterator<ClientExecutor> iterator = list.iterator();
    while (iterator.hasNext()) {
      ClientExecutor client = iterator.next();
      L1PcInstance tgpc = client.getActiveChar();
      if (tgpc != null)
        try {
          tgpc.save();
          tgpc.saveInventory();
        } catch (Exception e) {
          e.printStackTrace();
        }  
    } 
  }
}
